home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AOL File Library: 2,801 to 2,900
/
aol-file-protocol-4400-2801-to-2900.zip
/
AOLDLs
/
C++ Files Library
/
3D & Offscreen for MacApp 3
/
3D & Offscreen Sample.sea
/
3D & Offscreen Sample
/
T3DObjectView.cp
< prev
next >
Wrap
Text File
|
1993-05-21
|
19KB
|
666 lines
/*************************************************************************
File: T3DObjectView.h
C O P Y R I G H T N O T I C E
Copyright ⌐ 1989, 1990, 1991, 1992 Siemens Gammasonics, Inc.
All Rights Reserved.
No portions of this source code or the resulting compiled
program may be used without express written consent and liscensing
by Siemens Gammasonics, Inc.
D E S C R I P T I O N
Classes Defined Here:
Ñ
Change History
Rev 1 Wed, Apr 14, 1993 @ 1:17 PM Hanig
Creation
*************************************************************************/
/*************************************************************************/
/* Include Files */
/*************************************************************************/
#ifndef __T3DObjectView__
#include "T3DObjectView.h"
#endif
#ifndef __TVirtualSphere3DTracker__
#include "TVirtualSphere3DTracker.h"
#endif
#ifndef __TOffscreenAdorner__
#include "TOffscreenAdorner.h"
#endif
#ifndef __RESOURCES__
#include <Resources.h>
#endif
#ifndef __UMACAPPUTILITIES__
#include <UMacAppUtilities.h>
#endif
#ifndef __UFAILURE__
#include <UFailure.h>
#endif
#ifndef __UDOCUMENT__
#include <UDocument.h>
#endif
#ifndef __UDIALOG__
#include <UDialog.h>
#endif
#ifndef __UERRORMGR__
#include <UErrorMgr.h>
#endif
#ifndef __UMENUMGR__
#include <UMenuMgr.h>
#endif
#ifndef __MATH__
#include <Math.h>
#endif
#ifndef __FIXMATH__
#include <FixMath.h>
#endif
#ifndef _SANE_
#include <SANE.h>
#endif
#ifndef __LIMITS__
#include <Limits.h>
#endif
#include "Consts.h"
/*************************************************************************/
/* Constants */
/*************************************************************************/
const short rDitherPatterns = 128;
#define kRWeight 6
#define kGWeight 4
#define kBWeight 3
#define kTotalWeight (kRWeight + kGWeight + kBWeight)
/*************************************************************************/
T3DObjectView::T3DObjectView( void )
{
}
/*************************************************************************/
#pragma segment MAOpen
pascal void T3DObjectView::Initialize()
{
inherited::Initialize ();
fPolyNet = NULL;
fDrawInColor = gConfiguration.hasColorQD;
fPolyShade = NULL;
fRemoveBackfacedPolygon = true;
fRenderingStyle = iFlatShadingWithOutline; // iLineDrawing, iFlatShading, iFlatShadingWithOutline
f3DTracker = cRotationTracker;
// preload dither patterns for black & white.
PatListHandle theDitherPatterns;
theDitherPatterns = (PatListHandle) GetResource ('PAT#', rDitherPatterns);
DetachResource ((Handle) theDitherPatterns);
FailMemError();
MoveHHi ((Handle) theDitherPatterns );
FailMemError();
HNoPurge ((Handle) theDitherPatterns );
FailMemError();
HLock ((Handle) theDitherPatterns);
FailMemError();
fDitherPatterns = theDitherPatterns;
// Set matrix to Null
fObjectMatrix [0][0] = fObjectMatrix [1][1] = fObjectMatrix [2][2] = fObjectMatrix [3][3] = 1;
fObjectMatrix [0][1] = fObjectMatrix [0][2] = fObjectMatrix [0][3] =
fObjectMatrix [1][0] = fObjectMatrix [1][2] = fObjectMatrix [1][3] =
fObjectMatrix [2][0] = fObjectMatrix [2][1] = fObjectMatrix [2][3] =
fObjectMatrix [3][0] = fObjectMatrix [3][1] = fObjectMatrix [3][2] = 0;
}
/*************************************************************************/
#pragma segment MAOpen
pascal void T3DObjectView::DoPostCreate(TDocument* itsDocument)
{
inherited::DoPostCreate (itsDocument);
// This will add transparent offscreen handling.
// Due to an Error in MacApp, the Adorner must be added manually
TOffscreenAdorner* aOffscreenAdorner = new TOffscreenAdorner;
aOffscreenAdorner->IOffscreenAdorner('OffA', true, false );
this->AddAdorner (aOffscreenAdorner, kAdornFirst, false);
CRect drawArea;
Fixed cubeSize;
this->GetQDExtent (drawArea);
long shortestSide = drawArea.right;
if ( drawArea.bottom < drawArea.right )
shortestSide = drawArea.bottom;
cubeSize = MyLong2Fix((long)(shortestSide));
LookAt ( -cubeSize, cubeSize, cubeSize, -cubeSize );
ViewAngle (MyLong2Fix (25));
Scale (MyLong2Fix (1), MyLong2Fix (1), MyLong2Fix (1));
Matrix2XfMatrix (fObjectMatrix, fThe3DPort.xForm);
this->SetObjectType (cIcosahedron);
}
/*************************************************************************/
#pragma segment MAViewNonRes
pascal void T3DObjectView::SetFrame(const VRect& newFrame, Boolean invalidate)
{
inherited::SetFrame (newFrame, invalidate);
// maybe we should scale here.
this->ForceRedraw();
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::Matrix2XfMatrix (Matrix4D fromMatrix, XfMatrix toMatrix)
{
long i, j;
for (i=3; i>=0; i--)
for (j=3; j>=0; j--)
toMatrix[i][j]= X2Fix (fromMatrix[i][j]);
#ifdef xxxxxxxxxxxxxxxxxxxxxxxxxNOT_USEDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
/* Faster but kludgy version of the same thing */
double *fromPtr = (double *) fromMatrix;
Fixed *toPtr = (Fixed *) toMatrix;
long i;
for (i=15; i>=0; i--) {
*toPtr++ = X2Fix (*fromPtr++);
}
#endif xxxxxxxxxxxxxxxxxxxxxxxxxNOT_USEDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::MultiplyMatrix (Matrix4D a, Matrix4D b, Matrix4D aTimesB)
{
long i, j, k;
for (i=3; i>=0; i--)
{
for (j=3; j>=0; j--)
{
double sum = 0.0;
for (k=3; k>=0; k--)
sum += a[i][k] * b[k][j];
aTimesB[i][j]= sum;
}
}
}
/*************************************************************************/
#pragma segment MAViewRes
pascal void T3DObjectView::Draw(const VRect& /*area*/)
{
CRect drawArea;
short shortestSide;
short sphereRadius;
DrawPolyNet (); // draw polygon
PenNormal(); // with only line drawing on, the pen gets set
// dont draw oval at edges of frame
this->GetQDExtent (drawArea);
shortestSide = drawArea.right;
if ( drawArea.right > drawArea.bottom )
shortestSide = drawArea.bottom;
shortestSide = shortestSide/2;
sphereRadius = (short)(shortestSide * kSphereRadius);
SetRect(drawArea, shortestSide - sphereRadius, shortestSide - sphereRadius,
shortestSide + sphereRadius, shortestSide + sphereRadius );
FrameOval (drawArea);
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::DrawPolyNet ( )
{
if ( fPolyNet )
{
Point3D* vertices; // local index into the vertex array
long* vertexIndices;
long count;
if (fPolyNet->fVertexCount < 0)
return;//DebugMessage ("\pfVertexCount < 0");
vertices = fPolyNet->fVertices;
vertexIndices = fPolyNet->fVertexIndices;
// For each polygon...
for (count = 0; count < fPolyNet->fPolygonCount; count++)
{
long firstVertexIndex;
NetPolygon* thisPoly = &fPolyNet->fPolys[count];
if (thisPoly->fVertexCount < 3)
continue; // This is not a polygon. Skip to next one.
firstVertexIndex = thisPoly->fFirstVertexIndex;
if ( fRemoveBackfacedPolygon )
{
// Transform first 3 points to screen coordinate to do backface polygon test.
// Code will not work if any vertex is offscreen!
CPoint p0, p1, p2;
long v1h, v1v, v2h, v2v;
MoveTo3D (vertices [vertexIndices [firstVertexIndex ]].x,
vertices [vertexIndices [firstVertexIndex ]].y,
vertices [vertexIndices [firstVertexIndex ]].z);
GetPen (p0);
MoveTo3D (vertices [vertexIndices [firstVertexIndex+1]].x,
vertices [vertexIndices [firstVertexIndex+1]].y,
vertices [vertexIndices [firstVertexIndex+1]].z);
GetPen (p1);
MoveTo3D (vertices [vertexIndices [firstVertexIndex+2]].x,
vertices [vertexIndices [firstVertexIndex+2]].y,
vertices [vertexIndices [firstVertexIndex+2]].z);
GetPen (p2);
v1h = p1.h - p0.h;
v1v = p1.v - p0.v;
v2h = p2.h - p1.h;
v2v = p2.v - p1.v;
// Check for backfaced polygon by doing cross-product. Skip if backfaced.
// Try using '<=' test instead to get the inside-out effect
if ((v1h * v2v - v1v * v2h) >= 0)
continue;
}
{
// Draw the polygon
PolyHandle polyHdl = nil;
long j;
long vertexIndex;
if (fRenderingStyle != iLineDrawing)
{
// fRenderingStyle is iFlatShading or iFlatShadingWithOutline.
// Begin collecting QD polygon
polyHdl = OpenPoly ();
}
PolyColor (fPolyNet->fColor[thisPoly->fColorIndex]);
// Initial move
vertexIndex = vertexIndices [firstVertexIndex];
MoveTo3D ( vertices [vertexIndex].x,
vertices [vertexIndex].y,
vertices [vertexIndex].z);
// Hit the vertices
for (j = firstVertexIndex+1; j < firstVertexIndex+thisPoly->fVertexCount; j++)
{
vertexIndex = vertexIndices [j];
LineTo3D( vertices [vertexIndex].x,
vertices [vertexIndex].y,
vertices [vertexIndex].z);
}
// Close the polygon
vertexIndex = vertexIndices [firstVertexIndex];
LineTo3D ( vertices [vertexIndex].x,
vertices [vertexIndex].y,
vertices [vertexIndex].z);
if (fRenderingStyle != iLineDrawing)
{
ClosePoly (); // Stop collecting QD polygon
FillPoly (polyHdl, fPolyShade);
if (fRenderingStyle == iFlatShadingWithOutline)
{
ForeColor (blackColor);
FramePoly (polyHdl);
}
KillPoly (polyHdl);
}
}
}
}
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::SetPolyNet( PolygonNetData* thePolyNet )
{
fPolyNet = thePolyNet;
this->ForceRedraw();
}
/*************************************************************************/
#pragma segment MASelCommand
pascal void T3DObjectView::DoMouseCommand(VPoint& theMouse, TToolboxEvent* event, CPoint hysteresis)
{
switch ( f3DTracker )
{
case cRotationTracker:
TVirtualSphere3DTracker * a3DVirtualTracker = new TVirtualSphere3DTracker;
a3DVirtualTracker->I3DTracker(this, theMouse);
this->PostCommand(a3DVirtualTracker);
case cScaleTracker: // future trackers
// TScale3DTracker * a3DScaleTracker = new TScale3DTracker;
// a3DScaleTracker->I3DTracker(this, theMouse);
// this->PostCommand(a3DScaleTracker);
// break;
default:
inherited::DoMouseCommand (theMouse, event, hysteresis);
break;
}
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::PolyColor (const CRGBColor& rGBColor)
{
if (fDrawInColor)
{
fPolyShade = (ConstPatternParam)(&qd.black);
RGBForeColor (rGBColor);
}
else
{
// Convert RGB to dither pattern. Note we use different weighting factors
// for the RGB components to come up with a grey value. This is just
// so that more different patterns are shown on the objects. Note RGB components are shorts.
unsigned long index;
unsigned long intensity;
long kMaxPatternIndex = (**fDitherPatterns).patListSize;
intensity = kRWeight*rGBColor.red + kGWeight*rGBColor.green + kBWeight*rGBColor.blue;
index = intensity * kMaxPatternIndex / kTotalWeight / USHRT_MAX; // Note long math. Order matters
if (index >= kMaxPatternIndex)
index = kMaxPatternIndex -1; // Needed?
fPolyShade = (ConstPatternParam) (&((**fDitherPatterns).patList[index]));
ForeColor (blackColor);
}
}
/*************************************************************************/
#pragma segment MAClose
pascal void T3DObjectView::Free()
{
if ( fDitherPatterns == NULL )
DisposeHandle ((Handle) fDitherPatterns);
inherited::Free();
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::CopyMatrix (Matrix4D fromMatrix, Matrix4D toMatrix)
{
* (MatrixAsStruct *) toMatrix = * (MatrixAsStruct *) fromMatrix;
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::SetRotationMatrix (Matrix4D rotationMatrix, const CPoint3D *axis, double radians)
{
double s, c, t;
#define ax (axis->x)
#define ay (axis->y)
#define az (axis->z)
#define ax2 (ax * ax)
#define ay2 (ay * ay)
#define az2 (az * az)
s = sin (radians);
c = cos (radians);
t = 1 - c;
rotationMatrix[0][0] = t*ax2+c;
rotationMatrix[0][1] = t*ax*ay+s*az;
rotationMatrix[0][2] = t*ax*az-s*ay;
rotationMatrix[1][0] = t*ax*ay-s*az;
rotationMatrix[1][1] = t*ay2+c;
rotationMatrix[1][2] = t*ay*az+s*ax;
rotationMatrix[2][0] = t*ax*az+s*ay;
rotationMatrix[2][1] = t*ay*az-s*ax;
rotationMatrix[2][2] = t*az2+c;
rotationMatrix[0][3] = rotationMatrix[1][3] = rotationMatrix[2][3] =
rotationMatrix[3][0] = rotationMatrix[3][1] = rotationMatrix[3][2] = 0.0;
rotationMatrix[3][3] = 1.0;
#undef ax
#undef ay
#undef az
#undef ax2
#undef ay2
#undef az2
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::AdjustforRotation(const CPoint3D* axis, double radians)
{
Matrix4D tempMatrix;
Matrix4D rotationMatrix;
this->SetRotationMatrix (rotationMatrix, axis, radians);
Boolean wasLocked = this->Lock(true); // using class variable, don't let float
this->MultiplyMatrix( fObjectMatrix, rotationMatrix, tempMatrix );
this->CopyMatrix (tempMatrix, fObjectMatrix);
this->OrthogonalizeRotationMatrix (fObjectMatrix);
this->Lock(wasLocked);
}
/*************************************************************************/
#pragma segment MAViewRes
pascal Boolean T3DObjectView::Focus()
{
Boolean result = inherited::Focus ();
Matrix2XfMatrix (fObjectMatrix, fThe3DPort.xForm);
return (result);
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::OrthogonalizeRotationMatrix (Matrix4D matrix)
{
CPoint3D xAxis, yAxis, zAxis;
yAxis.x = matrix[1][0];
yAxis.y = matrix[1][1];
yAxis.z = matrix[1][2];
zAxis.x = matrix[2][0];
zAxis.y = matrix[2][1];
zAxis.z = matrix[2][2];
Normalize3D (&yAxis);
UnitCrossProduct3D (&yAxis, &zAxis, &xAxis);
UnitCrossProduct3D (&xAxis, &yAxis, &zAxis);
matrix[0][0] = xAxis.x;
matrix[0][1] = xAxis.y;
matrix[0][2] = xAxis.z;
matrix[1][0] = yAxis.x;
matrix[1][1] = yAxis.y;
matrix[1][2] = yAxis.z;
matrix[2][0] = zAxis.x;
matrix[2][1] = zAxis.y;
matrix[2][2] = zAxis.z;
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::Normalize3D (CPoint3D* v)
{
double length;
length = sqrt (v->x * v->x + v->y * v->y + v->z * v->z);
if (length > 0)
{
v->x /= length;
v->y /= length;
v->z /= length;
}
else
{
// Vector is zero. This will cause the program to crash. So we
// get rid of the offending data, and start a new window.
v->x = v->y = v->z = 0;
ParamText("the vector was 0", "This error causes loss of matrix normalization.", "rotate the object", gEmptyString);
MacAppAlert(phGenError, NULL);
if ( fDocument )
this->fDocument->CloseAndFree ();
gApplication->DoMenuCommand (cNew);
Failure(0,0);
}
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::UnitCrossProduct3D (const CPoint3D *a, const CPoint3D *b, CPoint3D *aCrossB)
{
CrossProduct3D (a, b, aCrossB);
Normalize3D (aCrossB);
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::CrossProduct3D (const CPoint3D *a, const CPoint3D *b, CPoint3D *aCrossB)
{
aCrossB->x = a->y * b->z - a->z * b->y;
aCrossB->y = a->z * b->x - a->x * b->z;
aCrossB->z = a->x * b->y - a->y * b->x;
}
/*************************************************************************/
#pragma segment MASelCommand
pascal void T3DObjectView::DoMenuCommand(CommandNumber aCommandNumber)
{
switch (aCommandNumber)
{
case cLineDraw:
fRenderingStyle = iLineDrawing;
this->ForceRedraw();
break;
case cFlatShading:
fRenderingStyle = iFlatShading;
this->ForceRedraw();
break;
case cFlatwithOutline:
fRenderingStyle = iFlatShadingWithOutline;
this->ForceRedraw();
break;
case cBackFacePolyremove:
fRemoveBackfacedPolygon = !fRemoveBackfacedPolygon;
this->ForceRedraw();
break;
case cRemoveOffscreen:
break;
case cCube:
case cHouse:
case cIcosahedron:
SetObjectType (aCommandNumber);
break;
case cRotationTracker:
case cScaleTracker:
case cViewTracker:
f3DTracker = aCommandNumber;
break;
default:
inherited::DoMenuCommand(aCommandNumber);
break;
}
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::DoSetupMenus()
{
inherited::DoSetupMenus();
EnableCheck(cLineDraw, true, fRenderingStyle == iLineDrawing);
EnableCheck(cFlatShading, true, fRenderingStyle == iFlatShading);
EnableCheck(cFlatwithOutline, true, fRenderingStyle == iFlatShadingWithOutline);
EnableCheck(cBackFacePolyremove,true, fRemoveBackfacedPolygon);
EnableCheck(cCube, true, f3DObject == cCube );
EnableCheck(cHouse, true, f3DObject == cHouse );
EnableCheck(cIcosahedron, true, f3DObject == cIcosahedron );
EnableCheck(cRotationTracker, true, f3DTracker == cRotationTracker );
EnableCheck(cScaleTracker, false, f3DTracker == cScaleTracker );
EnableCheck(cViewTracker, false, f3DTracker == cViewTracker );
}
/*************************************************************************/
#pragma segment ThreeDSeg
pascal void T3DObjectView::SetObjectType(CommandNumber newObject)
{
f3DObject = newObject;
// Set matrix to Null
//fObjectMatrix [0][0] = fObjectMatrix [1][1] = fObjectMatrix [2][2] = fObjectMatrix [3][3] = 1;
//fObjectMatrix [0][1] = fObjectMatrix [0][2] = fObjectMatrix [0][3] =
//fObjectMatrix [1][0] = fObjectMatrix [1][2] = fObjectMatrix [1][3] =
//fObjectMatrix [2][0] = fObjectMatrix [2][1] = fObjectMatrix [2][3] =
//fObjectMatrix [3][0] = fObjectMatrix [3][1] = fObjectMatrix [3][2] = 0;
//Matrix2XfMatrix (fObjectMatrix, fThe3DPort.xForm);
switch (newObject)
{
case cCube:
this->SetPolyNet (&gCubeData);
break;
case cHouse:
this->SetPolyNet (&gHouseData);
break;
case cIcosahedron:
this->SetPolyNet (&gIcosahedronData);
break;
default:
this->SetPolyNet (&gIcosahedronData);
f3DObject = cIcosahedron;
break;
}
}
/*************************************************************************/
/*************************************************************************/